#include "esp_http_client.h"
#include "lwip/dns.h"
#include "lwip/err.h"
#include "lwip/ip_addr.h"
#include "lwip/netdb.h"
#include "lwip/sys.h"
#include <sys/socket.h>
#include "Drivers/spiffs_drv.h"
#include "esp_log.h"
#include "Drivers/tcp_drv.h"
#include "Drivers/uart_drv.h"
#include "App/http_client_task.h"

#define FILE_URL "http://192.168.0.83:8080/DEMO3.bin"       //测试

#define TAG     "HTTP_CLIENT"

// EventGroupHandle_t GetBinEventGroup = NULL;

SemaphoreHandle_t xDownloadSemaphore = NULL;                //下载文件信号量

/**
 * @brief HTTP 客户端事件处理回调函数
 *
 * 处理 HTTP 客户端在请求过程中的各种事件，包括：
 * - 错误事件
 * - 连接建立
 * - 头部发送
 * - 接收头部
 * - 接收数据
 * - 请求完成
 * - 连接断开
 * - 重定向
 *
 * 当接收到数据时，将数据写入指定文件。
 *
 * @param[in] evt HTTP 客户端事件结构体指针
 * @return esp_err_t 返回 ESP_OK 表示成功，ESP_FAIL 表示失败
 */
static esp_err_t http_event_handler(esp_http_client_event_t *evt)
{
    switch (evt->event_id)
    {
    case HTTP_EVENT_ERROR:
        printf("HTTP_EVENT_ERROR\n");
        break;
    case HTTP_EVENT_ON_CONNECTED:
        printf("HTTP_EVENT_ON_CONNECTED\n");
        break;
    case HTTP_EVENT_HEADER_SENT:
        printf("HTTP_EVENT_HEADER_SENT\n");
        break;
    case HTTP_EVENT_ON_HEADER:
        printf("HTTP_EVENT_ON_HEADER, key=%s, value=%s\n", evt->header_key, evt->header_value);
        break;
    case HTTP_EVENT_ON_DATA:
        // printf("HTTP_EVENT_ON_DATA, len=%d\n", evt->data_len);
        if (!esp_http_client_is_chunked_response(evt->client))
        {
            // Write received data to a file
            FILE *f = fopen(FILE_PATH, "a");
            if (f == NULL)
            {
                printf("Failed to open file for writing\n");
                return ESP_FAIL;
            }
            fwrite(evt->data, 1, evt->data_len, f);
            fclose(f);
        }
        break;
    case HTTP_EVENT_ON_FINISH:
        printf("HTTP_EVENT_ON_FINISH\n");
        break;
    case HTTP_EVENT_DISCONNECTED:
        printf("HTTP_EVENT_DISCONNECTED\n");
        break;
    case HTTP_EVENT_REDIRECT:

        break;
    }
    return ESP_OK;
}

/**
 * @brief 下载文件任务函数
 *
 * 该函数作为一个独立任务运行,用于从指定URL下载文件并保存到SPIFFS文件系统中。
 * 主要功能包括:
 * - 获取下载URL
 * - 创建HTTP客户端并配置
 * - 下载文件并保存到SPIFFS
 * - 下载成功后通知其他任务
 * - 发送bootloader指令到STC芯片
 *
 * @param param 任务参数(未使用)
 * @return void
 *
 * @note 文件打开失败会重启设备，并格式化SPIFFS
 */
void DownloadFileTask(void *param)
{
    ESP_LOGI(TAG, "DownloadFileTask");
    xDownloadSemaphore = xSemaphoreCreateBinary();
    char SetBootLoader[] = {0x01,0x06,0x00,0x1e,0x00,0x01,0x28,0x0c};       
   
    char *g_url = (char*)GetUrl();          //获取url
    if(g_url[0] == '\0') {
        goto url_fail;     //获取url失败
    }

    esp_http_client_config_t config = {
        .url = g_url,
        // .url = FILE_URL,                 //测试
        .event_handler = http_event_handler,
    };
    // ESP_LOGI(TAG,"stc url:%s",url);
    FILE *new_file = fopen(FILE_PATH,"wb");
    if(new_file == NULL)
    {
        ESP_LOGE(TAG,"open fail");
        esp_spiffs_format(NULL);        //格式化
        esp_restart();

    } 
    fclose(new_file);
    esp_http_client_handle_t client = esp_http_client_init(&config);

    esp_err_t err = esp_http_client_perform(client);
#if UART_LOG
    FILE *p = fopen(FILE_PATH,"rb"); 
    char buffer[1024] = {0};

    fread(buffer, sizeof(char), sizeof(buffer), p);

    fclose(p);
    for (size_t i = 0; i < sizeof(buffer); i++)
    {
    printf("%02x ",buffer[i]);
    }
#endif

    if (err == ESP_OK) 
    {
        // xEventGroupSetBits(GetBinEventGroup,DOWNLOAD_SUCCESS); 
        xSemaphoreGive(xDownloadSemaphore);                                     //下载成功信号量
        uart_write_bytes(UART_DATA_NUM, SetBootLoader, sizeof(SetBootLoader));  //设置stc进入bootloader
        printf("File downloaded successfully\n");   
    }
    else
        printf("File download failed\n");

    esp_http_client_cleanup(client);
url_fail:    

    vTaskDelete(NULL);
}

// void HttpClientTask(void *pvParameters)
// {
//     ESP_LOGI(TAG,"HttpClientTask");
//     // GetBinEventGroup = xEventGroupCreate();
    

    

//     // xTaskCreate(DownloadFileTask, "download_file_task", 1024 * 8, pvParameters, 7, NULL);
//     // xEventGroupWaitBits(GetBinEventGroup, DOWNLOAD_SUCCESS, false, true, portMAX_DELAY);
//     ESP_LOGI(TAG,"TaskDelete");
//     vTaskDelete(NULL);
// }
